/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   Module Name          : com.yaodian100.crm.cs.service.CsServiceImpl
   Module Description   :

   Date Created      : 2009/12/17
   Original Author   : andy.chuang
   Team              : yaodian100
   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   MODIFICATION HISTORY
   ------------------------------------------------------------------------------
   Date Modified       Modified by       Comments
   ------------------------------------------------------------------------------
   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
package com.yaodian100.crm.cs.service;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateUtils;
import org.apache.commons.lang.time.FastDateFormat;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Restrictions;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.transaction.annotation.Transactional;

import com.yaodian100.core.admin.entity.User;
import com.yaodian100.core.admin.utils.AdminHelper;
import com.yaodian100.core.common.exception.CoreException;
import com.yaodian100.core.common.service.BaseManager;
import com.yaodian100.core.form.entity.Attribute;
import com.yaodian100.core.mail.entity.Mail;
import com.yaodian100.core.mail.service.MailService;
import com.yaodian100.core.sms.service.SmsService;
import com.yaodian100.core.template.service.TemplateService;
import com.yaodian100.crm.cs.entity.CommonQuestionType;
import com.yaodian100.crm.cs.entity.FromChannel;
import com.yaodian100.crm.cs.entity.Question;
import com.yaodian100.crm.cs.entity.QuestionExtraValue;
import com.yaodian100.crm.cs.entity.QuestionType;
import com.yaodian100.crm.workorder.entity.WorkOrder;
import com.yaodian100.crm.workorder.service.WorkOrderService;
import com.yaodian100.ec.common.EcConstant;
import com.yaodian100.ec.common.EnvParameters;
import com.yaodian100.ec.member.entity.Balance;
import com.yaodian100.ec.member.entity.Bonus;
import com.yaodian100.ec.member.entity.Member;
import com.yaodian100.ec.member.service.MemberService;
import com.yaodian100.ec.order.entity.OrderProduct;
import com.yaodian100.ec.order.entity.Orders;
import com.yaodian100.ec.product.entity.Product;

/**
 * @author andy.chuang
 * 
 */
public class CsServiceImpl implements CsService {
	@Resource
	private BaseManager baseMgr;
	@Resource
	private WorkOrderService workOrderService;
	@Resource
	private MemberService memberService;
	@Resource
	private MailService mailService;
	@Resource
	private TemplateService velocityService;
	@Resource
	private EnvParameters envParameters;
	@Resource
	private JdbcTemplate jdbcTemplate;
	@Resource
	private SmsService smsService;

	// @Autowired
	// private QuestionAttachService questionAttachService;
	private QuestionAttachService questionAttachServiceRemote;

	@Transactional(readOnly = false)
	public void updateQuestion(String questionType, String id, String username, String fromChannel, String description,
			String shortDesc, String memberId) {
		try {
			Question question = null;
			QuestionType qt = null;
			if (questionType != null && questionType.length() > 0) {
				qt = (QuestionType) baseMgr.get(QuestionType.class, questionType);
			}
			if (id != null && id.length() > 0) {
				// update
				question = (Question) baseMgr.get(Question.class, id);

			} else {
				// save
				question = new Question();
				Date createDate = new Date();
				question.setCreateDate(createDate);
				question.setCreateUser(username);

			}
			FromChannel fc = null;
			if (fromChannel != null && fromChannel.length() > 0) {
				fc = new FromChannel();
				fc.setId(fromChannel);
			}
			question.setChannel(fc);

			// question.setType(qt);
			question.setDescription(description);
			question.setModifyUser(username);
			question.setShortDesc(shortDesc);
			if (memberId != null && memberId.length() > 0) {
				question.setMemberId(memberId);
			}

			// question.setProductId(Long.parseLong(productId));
			baseMgr.saveOrUpdate(question);

			if (id != null && id.length() > 0) {
				// update
				Map<String, QuestionExtraValue> valueMap = question.getExtraValue();
				List<Attribute> attrs = qt.getExtraAttr().getAttributes();
				for (int i = 0; i < attrs.size(); i++) {
					Attribute attr = attrs.get(i);
					QuestionExtraValue ea = valueMap.get(attr.getName());
					if (ea == null) {
						ea = new QuestionExtraValue();
					}
					ea.setQuestion(question);
					ea.setName(attr.getName());
					ea.setAttribute(attr);
					Field field = this.getClass().getDeclaredField(attr.getName());
					field.setAccessible(true);
					String value = (String) field.get(this);
					ea.setValue(value);
					baseMgr.saveOrUpdate(ea);
				}

			} else {
				// save
				List<Attribute> attrs = qt.getExtraAttr().getAttributes();
				for (int i = 0; i < attrs.size(); i++) {
					Attribute attr = attrs.get(i);
					QuestionExtraValue ea = new QuestionExtraValue();
					ea.setQuestion(question);
					ea.setName(attr.getName());
					ea.setAttribute(attr);
					Field field = this.getClass().getDeclaredField(attr.getName());
					field.setAccessible(true);
					String value = (String) field.get(this);
					ea.setValue(value);
					baseMgr.save(ea);
				}

			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	private void updateMemberBalance(Question question, boolean isProductQAA) {
		if (question.getMemberId() != null) {
			if (isProductQAA) {

				if (question.getMemberId() != null && !question.getMemberId().equals("")) {
					Balance balance = (Balance) baseMgr.get(Balance.class, question.getMemberId());
					// 商品问答 发问中
					String hql = "from Question q where q.memberId=? and q.type.name=? and q.answeredDate is null and q.extraValue['isProductQAA'].value=?";
					List<Object> params = new ArrayList<Object>();
					params.add(question.getMemberId());
					params.add("CommonQuestion");
					params.add("true");

					Long countQ = baseMgr.countByHql(hql, params.toArray());
					balance.setAskedProductQuestion(new BigDecimal(countQ));
					memberService.saveOrUpdateBalance(balance);
				}
			} else if (!isProductQAA) {
				Balance balance = (Balance) baseMgr.get(Balance.class, question.getMemberId());
				List<Object> params = new ArrayList<Object>();
				// 客服問答 發問中
				String hql = "from Question q where q.memberId=? and q.type.name=? and q.answeredDate is null and q.extraValue['isProductQAA'].value=?";
				params = new ArrayList<Object>();
				params.add(question.getMemberId());
				params.add("CommonQuestion");
				params.add("false");
				Long countQ = baseMgr.countByHql(hql, params.toArray());
				balance.setAskedCRM(new BigDecimal(countQ));
				memberService.saveOrUpdateBalance(balance);
			}
		}
	}

	@Transactional(readOnly = false)
	public void createProductQuestion(boolean isMember, String email, String memberId, String productId, String content) {
		String questionTypeName = "CommonQuestion";

		DetachedCriteria dc = DetachedCriteria.forClass(FromChannel.class);
		dc.add(Restrictions.eq("title", "WEB form"));
		Object[] channels = baseMgr.findByCriteria(dc);
		FromChannel channel = null;
		if (channels != null) {
			channel = ((FromChannel) channels[0]);
		}

		Map<String, String> values = new HashMap<String, String>();
		values.put("memberId", memberId);
		values.put("productId", productId);
		values.put("isProductQAA", "true");
		Question question = createQuestionBase(null, null, questionTypeName, values, content, content, channel, null);

		updateMemberBalance(question, true);
		QuestionType qt = (QuestionType) baseMgr.get(QuestionType.class, questionTypeName);
		workOrderService.createWorkOrder("SYSTEM", question.getId(), question.getShortDesc(), false, null);
		// Map<String, Object> objs=new HashMap<String, Object>();
		// objs.put("basehref", ServerValue.getFrontHostname());
		// Member member=(Member)baseMgr.get(Member.class, memberId);
		// objs.put("memberName", member.getLoginId());
		// Mail entity=velocityService.formatToMail("service_qa_confirm", objs);
		// mailService.save(entity);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.yaodian100.crm.cs.service.CsService#createCommonQuestion(java.lang.String, java.lang.String,
	 * java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String,
	 * java.lang.String)
	 */
	@Override
	@Transactional(readOnly = false)
	public void createCommonQuestion(String email, String memberId, String productId, String content, String phoneArea,
			String phone, String phoneExt, String orderId, String cellPhone, String class2, List<File> attach,
			List<String> attachFileName) {
		DetachedCriteria dc = DetachedCriteria.forClass(FromChannel.class);
		dc.add(Restrictions.eq("title", "WEB form"));
		Object[] channels = baseMgr.findByCriteria(dc);
		Question question = createCommonQuestionBase(email, memberId, productId, content, phoneArea, phone, phoneExt,
				orderId, cellPhone, class2, (FromChannel) channels[0]);

		ArrayList<byte[]> fileContentList = this.getFileContents(attach);
		ArrayList<String> fileNameList = new ArrayList<String>();
		if (attachFileName != null) {
			for (String fileName : attachFileName) {
				fileNameList.add(fileName);
			}
		}
		// 儲存附件
		this.questionAttachServiceRemote.saveAttach(question.getId(), fileContentList, fileNameList);

		// QuestionType qt=(QuestionType)baseMgr.get(QuestionType.class, questionTypeName);
		updateMemberBalance(question, false);
		workOrderService.createWorkOrder("SYSTEM", question.getId(), question.getShortDesc(), false, null);
		Map<String, Object> objs = new HashMap<String, Object>();
		if (memberId != null) {
			Member member = (Member) baseMgr.get(Member.class, memberId);
			objs.put("basehref", "http://" + member.getDomainSrc());
			objs.put("memberName", member.getLoginId());
			objs.put("domainSrc", member.getDomainSrc());
			Mail entity = velocityService.formatToMail("service_qa_ask", objs);
			entity.addTo(member.getLoginId(), member.getEmail());
			entity.setFrom(envParameters.getEmailFromCs());
			mailService.save(entity);
		}
	}

	private ArrayList<byte[]> getFileContents(List<File> attach) throws CoreException {
		ArrayList<byte[]> list = new ArrayList<byte[]>();
		if (attach == null) {
			return list;
		}
		for (File f : attach) {
			byte[] data = this.readFileContent(f);
			list.add(data);
		}
		return list;
	}

	private byte[] readFileContent(File file) throws CoreException {
		ByteArrayOutputStream out = null;
		FileInputStream in = null;
		try {
			out = new ByteArrayOutputStream();
			in = new FileInputStream(file);
			byte[] b = new byte[256];
			while (in.read(b) != -1) {
				out.write(b);
			}
			return out.toByteArray();
		} catch (Exception e) {
			e.printStackTrace();
			throw new CoreException("QuestionAttachService:" + e.getMessage(), e);
		} finally {
			try {
				in.close();
			} catch (Exception e) {
			}
			try {
				out.close();
			} catch (Exception e) {
			}
		}
	}

	@Override
	@Transactional(readOnly = false)
	public void createCommonQuestion(String email, String memberId, String productId, String content, String phoneArea,
			String phone, String phoneExt, String orderId, String cellPhone, String class2) {
		this.createCommonQuestion(email, memberId, productId, content, phoneArea, phone, phoneExt, orderId, cellPhone,
				class2, null, null);
	}

	@Transactional(readOnly = false)
	public void createCommonQuestionFromInternal(String email, String memberId, String productId, String content,
			String phoneArea, String phone, String phoneExt, String orderId, String cellPhone, String class1, String class2,
			String commonQuestionType, String workFlowNodeId, Integer priority, String mustInquire, String answer) {
		DetachedCriteria dc = DetachedCriteria.forClass(FromChannel.class);
		dc.add(Restrictions.eq("title", "内部人员"));
		Object[] channels = baseMgr.findByCriteria(dc);
		Question question = createCommonQuestionBase(email, memberId, productId, content, phoneArea, phone, phoneExt,
				orderId, cellPhone, class2, (FromChannel) channels[0]);
		WorkOrder wo = workOrderService.createWorkOrder("SYSTEM", question.getId(), question.getShortDesc(), false,
				AdminHelper.getUser());
		workOrderService.forwardOrder(String.valueOf(wo.getId()), content, null, workFlowNodeId, priority, class1, class2,
				commonQuestionType, mustInquire, answer, String.valueOf(false));
	}

	private Question createCommonQuestionBase(String email, String memberId, String productId, String content,
			String phoneArea, String phone, String phoneExt, String orderId, String cellPhone, String class2,
			FromChannel channel) {
		String questionTypeName = "CommonQuestion";

		CommonQuestionType cqt = (CommonQuestionType) baseMgr.get(CommonQuestionType.class, class2);
		String class1 = cqt.getParent().getId();
		Map<String, String> values = new HashMap<String, String>();
		values.put("memberId", memberId);
		values.put("orderId", orderId);
		values.put("productId", productId);
		values.put("phoneArea", phoneArea);
		values.put("phone", phone);
		values.put("phoneExt", phoneExt);
		values.put("cellPhone", cellPhone);
		values.put("class1", class1);
		values.put("class2", class2);
		values.put("isProductQAA", "false");
		values.put("email", email);
		Question question = createQuestionBase(null, null, questionTypeName, values, content, content, channel, null);
		// QuestionType qt=(QuestionType)baseMgr.get(QuestionType.class, questionTypeName);
		return question;

	}

	@Transactional(readOnly = false)
	public void createPayByProductArrive(String memberId, String orderId, String content) {
		String questionTypeName = "PayByProductArrive";

		DetachedCriteria dc = DetachedCriteria.forClass(FromChannel.class);
		dc.add(Restrictions.eq("title", "WEB form"));
		Object[] channels = baseMgr.findByCriteria(dc);
		FromChannel channel = null;
		if (channels != null) {
			channel = ((FromChannel) channels[0]);
		}

		Map<String, String> values = new HashMap<String, String>();
		values.put("orderId", orderId);
		Question question = createQuestionBase(null, null, questionTypeName, values, content, content, channel, null);
		workOrderService.createWorkOrder("SYSTEM", question.getId(), question.getShortDesc(), false, null);
		/*
		 * Map<String, Object> objs=new HashMap<String, Object>(); objs.put("basehref", ServerValue.getFrontHostname());
		 * 
		 * objs.put("memberName", member.getLoginId()); Mail entity=velocityService.formatToMail("service_qa_ask", objs);
		 * entity.addTo(member.getLoginId(), member.getEmail()); entity.setFrom(envParameters.getEmailFromCs());
		 * mailService.save(entity);
		 */
	}

	@Transactional(readOnly = false)
	public void createHighPriceOrder(String memberId, String orderId, String content) {
		String questionTypeName = "HighPriceOrder";

		DetachedCriteria dc = DetachedCriteria.forClass(FromChannel.class);
		dc.add(Restrictions.eq("title", "WEB form"));
		Object[] channels = baseMgr.findByCriteria(dc);
		FromChannel channel = null;
		if (channels != null) {
			channel = ((FromChannel) channels[0]);
		}

		Map<String, String> values = new HashMap<String, String>();
		values.put("orderId", orderId);
		values.put("memberId", memberId);
		Question question = createQuestionBase(null, null, questionTypeName, values, content, content, channel, null);
		workOrderService.createWorkOrder("SYSTEM", question.getId(), question.getShortDesc(), false, null);
		/*
		 * Map<String, Object> objs=new HashMap<String, Object>(); objs.put("basehref", ServerValue.getFrontHostname());
		 * 
		 * objs.put("memberName", member.getLoginId()); Mail entity=velocityService.formatToMail("service_qa_ask", objs);
		 * entity.addTo(member.getLoginId(), member.getEmail()); entity.setFrom(envParameters.getEmailFromCs());
		 * mailService.save(entity);
		 */
	}

	@Transactional(readOnly = false)
	public WorkOrder createPartialCancelOrder(String orderId, String productId, String content, FromChannel channel) {
		String questionTypeName = "PartialCancelOrder";

		Map<String, String> values = new HashMap<String, String>();
		values.put("orderId", orderId);
		values.put("productId", productId);
		Question question = createQuestionBase(null, null, questionTypeName, values, content, content, channel, null);

		return workOrderService.createWorkOrder("SYSTEM", question.getId(), question.getShortDesc(), false, null);
		/*
		 * Map<String, Object> objs=new HashMap<String, Object>(); objs.put("basehref", ServerValue.getFrontHostname());
		 * 
		 * objs.put("memberName", member.getLoginId()); Mail entity=velocityService.formatToMail("service_qa_ask", objs);
		 * entity.addTo(member.getLoginId(), member.getEmail()); entity.setFrom(envParameters.getEmailFromCs());
		 * mailService.save(entity);
		 */
	}

	@Transactional(readOnly = false)
	public Question createOutOfStockQuestion(String orderId, String productIds, String reason, String comment,
			FromChannel channel, String creater) {
		String questionTypeName = "OutOfStock";
		Map<String, String> values = new HashMap<String, String>();
		values.put("orderId", orderId);
		values.put("productId", productIds);
		values.put("cancelReason", reason);
		Question question = createQuestionBase(null, null, questionTypeName, values, comment, comment, channel, creater);

		return question;
	}

	/**
	 * 人工验证手机
	 * 
	 * from 0:注册 1:修改 2:订单
	 */
	@Override
	@Transactional(readOnly = false)
	public String createCrmCheckMobile(String mobile, String creater, String from) {
		String sql = "select domainid from crm_work_order "
				+ "where domainid in (select id from crm_cs_question where memberid = '" + creater
				+ "' and type_name = 'CheckMobile' and status not in (2,3)) order by createdate desc";
		List<Map<String, Object>> qList = jdbcTemplate.queryForList(sql);
		if (null != qList && !qList.isEmpty()) {
			return qList.get(0).get("DOMAINID").toString();
		}
		String questionTypeName = "CheckMobile";
		Map<String, String> values = new HashMap<String, String>();
		values.put("mobile", mobile);
		values.put("memberId", creater);
		DetachedCriteria dc = DetachedCriteria.forClass(FromChannel.class);
		dc.add(Restrictions.eq("title", "WEB form"));
		Object[] channels = baseMgr.findByCriteria(dc);
		FromChannel channel = null;
		if (channels != null) {
			channel = ((FromChannel) channels[0]);
		}
		String comment = "请协助外拨验证手机，手机号码：" + mobile + "(" + ("0".equals(from) ? "注册" : ("1".equals(from) ? "修改" : "订单"))
				+ ")";
		Question question = createQuestionBase(null, null, questionTypeName, values, comment, comment, channel, creater);
		WorkOrder wo1 = workOrderService.createWorkOrder("SYSTEM", question.getId(), question.getShortDesc(), false, null);
		WorkOrder wo2 = workOrderService.forwardOrder(wo1, comment, "sms", "C.01", "8ae4838832c76cc20132c7e8eaaf06c1", 1);
		return wo2.getDomainId();
	}

	public Question createQuestionBase(String questionId, String orgQuestionId, String questionTypeName,
			Map<String, String> values, String description, String comment, FromChannel channel, String creater) {
		QuestionType type = (QuestionType) baseMgr.get(QuestionType.class, questionTypeName);
		Question question = null;
		if (questionId == null || questionId.length() == 0) {
			question = new Question();
		} else {
			question = (Question) baseMgr.get(Question.class, questionId);
		}
		question.setDescription(description);
		question.setComment(comment);
		question.setType(type);
		Date createDT = new Date();
		question.setCreateDate(createDT);
		Object ob = values.get("memberId");
		if (ob instanceof String[]) {
			question.setMemberId(((String[]) ob)[0]);
		} else {
			question.setMemberId(values.get("memberId"));
		}
		ob = values.get("email");
		if (ob instanceof String[]) {
			question.setEmail(((String[]) ob)[0]);
		} else {
			question.setEmail(values.get("email"));
		}

		if (orgQuestionId != null && orgQuestionId.length() > 0) {
			while (true) {
				Object[] qs = baseMgr.queryByHql("from Question where orgQuestionId=?", new Object[] { (orgQuestionId) });
				if (qs != null && qs.length > 0) {
					for (Object obj : qs) {
						Question q = (Question) obj;
						orgQuestionId = String.valueOf(q.getId());
					}
				} else {
					break;
				}
			}
			// 检查工单状态
			Object[] wos = baseMgr.queryByHql("from WorkOrder where domainId=? order by id desc",
					new Object[] { orgQuestionId }, 0, 1);

			WorkOrder theLastWo = null;
			if (wos != null && wos.length > 0) {
				theLastWo = (WorkOrder) wos[0];
			}
			if (theLastWo.getStatus() == WorkOrder.STATUS.INIT.value() && theLastWo.getOwner() != null) {
				// 正在处理中，不产生新的问题单
				return theLastWo.getQuestion();
			}
			question.setOrgQuestionId(orgQuestionId);
			// 既已产生新问题单，将原问题单结束，并将所有相关工单结单为代结
			Question oldQuestion = (Question) baseMgr.get(Question.class, orgQuestionId);
			oldQuestion.setStatus(2);
			baseMgr.update(oldQuestion);
			String hqlNeedToClose = "from WorkOrder where question.id=? and status!=?";
			Object[] ncwos = baseMgr.queryByHql(hqlNeedToClose, new Object[] { orgQuestionId, 2 });
			if (ncwos != null && ncwos.length > 0) {
				for (Object obj : ncwos) {
					WorkOrder wo = (WorkOrder) obj;
					wo.setNote((wo.getNote() != null ? wo.getNote() : "") + " " + "自动结单 代结："
							+ AdminHelper.getUser().getUsername());
					wo.setApproveStatus(1);
					wo.setStatus(2);
					baseMgr.update(wo);
				}
			}
		}
		// 商品線＆配送商
		String productId = null;
		ob = values.get("productId");
		if (ob instanceof String[]) {
			productId = ((String[]) ob)[0];
		} else {
			productId = (String) ob;
		}

		if (productId != null && productId.length() > 0) {
			String productLine = "";
			String reg = ",";
			if (productId.indexOf(" ") > 0 && productId.indexOf(",") < 0) {
				reg = " ";
			}
			String[] ids = productId.split(reg);
			for (String id : ids) {
				Product product = (Product) baseMgr.get(Product.class, id);
				if (!productLine.equals("")) {
					productLine += ",";
				}
				productLine += product.getCategory().getRootId();
			}
			question.setCategory(productLine);
		}
		String orderId = null;
		ob = values.get("orderId");
		if (ob instanceof String[]) {
			orderId = ((String[]) ob)[0];
		} else {
			orderId = (String) ob;
		}

		if (orderId != null && orderId.length() > 0) {
			List<String> deliverList = new ArrayList<String>();
			String delivers = "";
			String reg = ",";
			if (orderId.indexOf(" ") > 0 && orderId.indexOf(",") < 0) {
				reg = " ";
			}
			String[] ids = orderId.split(reg);
			for (String id : ids) {
				Object[] orderProducts = baseMgr.queryByHql("from OrderProduct where orderId=?", new Object[] { id });
				for (Object obj : orderProducts) {
					OrderProduct op = (OrderProduct) obj;
					if (op.getLogisticCompany() != null && op.getLogisticCompany().length() > 0) {
						if (deliverList.size() > 0) {
							for (String deliver : deliverList) {
								if (!deliver.equals(op.getLogisticCompany())) {
									deliverList.add(op.getLogisticCompany());
								}
							}
						} else {
							deliverList.add(op.getLogisticCompany());
						}
					}
				}

			}
			if (deliverList.size() > 0) {
				for (String deliver : deliverList) {
					if (!delivers.equals("")) {
						delivers += ",";
					}
					delivers += deliver;
				}
			}
			question.setDeliver(delivers);
		}

		question.setChannel(channel);
		question.setCreateUser(creater);
		baseMgr.saveOrUpdate(question);
		Map<String, QuestionExtraValue> valueMap = question.getExtraValue();
		boolean isNewValueMap = false;
		if (valueMap == null) {
			isNewValueMap = true;
			valueMap = new HashMap<String, QuestionExtraValue>();
		}
		for (Attribute attribute : type.getExtraAttr().getAttributes()) {
			if (attribute.getDataType().equals("Button")) {
				continue;
			}
			QuestionExtraValue ea = null;
			if (!isNewValueMap) {
				ea = valueMap.get(attribute.getName());
			}
			if (ea == null) {
				ea = new QuestionExtraValue();
			}
			ea.setQuestion(question);
			ea.setName(attribute.getName());
			ea.setAttribute(attribute);
			for (String key : values.keySet()) {
				if (ea.getName().equals(key)) {
					Object obj = values.get(key);
					String value = null;
					if (obj instanceof String[]) {
						value = ((String[]) obj)[0];
					} else {
						value = (String) obj;
					}
					ea.setValue(value);
				}
			}
			baseMgr.saveOrUpdate(ea);
			valueMap.put(ea.getName(), ea);
		}
		question.setExtraValue(valueMap);
		return question;
	}

	@Transactional(readOnly = false)
	public void forwardOrderForOutOfStockInternal(String orderId, String productIds, String reason, String comment,
			String creater) {
		DetachedCriteria dc = DetachedCriteria.forClass(FromChannel.class);
		dc.add(Restrictions.eq("title", "内部人员"));
		Object[] channels = baseMgr.findByCriteria(dc);
		Question question = createOutOfStockQuestion(orderId, productIds, reason, comment, (FromChannel) channels[0],
				creater);
		User owner = (User) baseMgr.get(User.class, creater);
		WorkOrder wo = workOrderService.createWorkOrder("SYSTEM", question.getId(), question.getShortDesc(), false, owner);
		String workFlowNodeId = "ff8081812e33080f012e3322560b0001";// 断缺货流程一线客服节点
		// 这里的creater一定要传
		workOrderService.forwardOrderForRemote(String.valueOf(wo.getId()), comment, creater, "C.01", workFlowNodeId, 3);

		// 先检查是否已发过购物金(不允许重复发送)
		int stockNum = jdbcTemplate.queryForInt("select count(*) from EC_SPEC_INVENTORY_VALID where VALID_ID = '" + orderId
				+ "outStock" + "'");
		if (stockNum == 0) {
			StringBuffer sql = new StringBuffer("insert into EC_SPEC_INVENTORY_VALID (VALID_ID) values (?) ");
			jdbcTemplate.update(sql.toString(), new Object[] { orderId + "outStock" });
			sendOutOfStockMailAndBonus(wo, orderId, productIds);
		}
	}

	@Transactional(readOnly = false)
	public void forwardOrderForOutOfStockInternalBatch(String[] orderIdsAndProductIds, String reason, String comment,
			String creater) {
		DetachedCriteria dc = DetachedCriteria.forClass(FromChannel.class);
		dc.add(Restrictions.eq("title", "内部人员"));
		Object[] channels = baseMgr.findByCriteria(dc);
		User owner = (User) baseMgr.get(User.class, creater);
		for (String orderIdAndProductId : orderIdsAndProductIds) {
			String[] splitStr = orderIdAndProductId.split(" ");
			String orderId = splitStr[0];
			String productIds = "";
			if (splitStr.length > 1) {
				productIds = splitStr[1];
			}
			Question question = createOutOfStockQuestion(orderId, productIds, reason, comment, (FromChannel) channels[0],
					creater);

			WorkOrder wo = workOrderService
					.createWorkOrder("SYSTEM", question.getId(), question.getShortDesc(), false, owner);
			String workFlowNodeId = "ff8081812e33080f012e3322560b0001";// 断缺货流程一线客服节点
			workOrderService.forwardOrder(String.valueOf(wo.getId()), comment, null, workFlowNodeId, 3);
			// 先检查是否已发过购物金(不允许重复发送)
			int stockNum = jdbcTemplate.queryForInt("select count(*) from EC_SPEC_INVENTORY_VALID where VALID_ID = '"
					+ orderId + "outStock" + "'");
			if (stockNum == 0) {
				StringBuffer sql = new StringBuffer("insert into EC_SPEC_INVENTORY_VALID (VALID_ID) values (?) ");
				jdbcTemplate.update(sql.toString(), new Object[] { orderId + "outStock" });
				sendOutOfStockMailAndBonus(wo, orderId, productIds);
			}
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.yaodian100.crm.cs.service.CsService#sendOutOfStockMailAndBonus(java.lang.String, java.lang.String,
	 * java.lang.String)
	 */
	@Override
	@Transactional(readOnly = false)
	public void sendOutOfStockMailAndBonus(WorkOrder wo, String orderId, String productIds) {
		// 发送断货通知信
		Object[] orders = baseMgr.queryByHql("from Orders where orderId = ? ", new Object[] { orderId });
		if (null != orders && orders.length > 0) {
			Orders order = (Orders) orders[0];
			String[] prods = StringUtils.split(productIds, ",");
			StringBuffer params = new StringBuffer();
			for (int i = 0; i < prods.length; i++) {
				params.append("?");
				if (i < prods.length - 1) {
					params.append(" , ");
				}
			}
			Object[] productObjs = baseMgr.queryByHql("from Product where productId in ( " + params.toString() + " )", prods);
			if (!ArrayUtils.isEmpty(productObjs) && productObjs.length > 0) {
				// List<Product> products = new ArrayList<Product>();
				// for (Object obj : productObjs) {
				// products.add((Product) obj);
				// }
				// Map<String, Object> mailContentParameters = new HashMap<String, Object>();
				// mailContentParameters.put("order", order);
				// mailContentParameters.put("products", products);
				// mailContentParameters.put("orderDate", FastDateFormat.getInstance(EcConstant.PATTERN_TIMESTAMP_HH_MM).format(
				// order.getOrderDt()));
				// mailContentParameters.put("basehref", "http://" + order.getDomainSrc());
				// Mail stockMail = velocityService.formatToMail("outOfStockMail", mailContentParameters);
				// stockMail.addTo(order.getMemberName(), order.getReceiverEmail());
				// // stockMail.addTo("feeling", "feeling.wang@yaodian100.com");
				// stockMail.setFrom(envParameters.getEmailFromCs());
				// mailService.save(stockMail);

				// 发送购物金1000元
				Bonus bonus = new Bonus();
				bonus.setMemberId(order.getMemberId());
				bonus.setOrderId(orderId);
				bonus.setStartDate(DateUtils.addDays(wo.getCreateDate(), 1));
				bonus.setTrxDate(new Date());
				bonus.setExpireDate(DateUtils.addDays(bonus.getStartDate(), 30));
				bonus.setTrxAmount(new BigDecimal(1000));
				bonus.setDescription("断货补偿");
				bonus.setTrxType("ORDER_FEEDBACK");
				try {
					memberService.saveOrUpdateBonus(bonus);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
	}

	@Override
	@Transactional(readOnly = false)
	public void sendOutOfStockCancelOrder(WorkOrder wo, String orderId, String productIds) {
		// 結單整單取消-发送断货通知信
		Object[] orders = baseMgr.queryByHql("from Orders where orderId = ? ", new Object[] { orderId });
		if (null != orders && orders.length > 0) {
			Orders order = (Orders) orders[0];
			String[] prods = StringUtils.split(productIds, ",");
			StringBuffer params = new StringBuffer();
			for (int i = 0; i < prods.length; i++) {
				params.append("?");
				if (i < prods.length - 1) {
					params.append(" , ");
				}
			}
			Object[] productObjs = baseMgr.queryByHql("from Product where productId in ( " + params.toString() + " )", prods);
			if (!ArrayUtils.isEmpty(productObjs) && productObjs.length > 0) {
				List<Product> products = new ArrayList<Product>();
				for (Object obj : productObjs) {
					products.add((Product) obj);
				}
				Map<String, Object> mailContentParameters = new HashMap<String, Object>();
				mailContentParameters.put("order", order);
				mailContentParameters.put("products", products);
				mailContentParameters.put("orderDate", FastDateFormat.getInstance(EcConstant.PATTERN_TIMESTAMP_HH_MM).format(
						order.getOrderDt()));
				mailContentParameters.put("basehref", "http://" + order.getDomainSrc());
				Mail stockMail = velocityService.formatToMail("outOfStockCancelOrder", mailContentParameters);
				stockMail.addTo(order.getMemberName(), order.getReceiverEmail());
				// stockMail.addTo("feeling", "feeling.wang@yaodian100.com");
				stockMail.setFrom(envParameters.getEmailFromCs());
				mailService.save(stockMail);
				try {
					Member member = (Member) baseMgr.get(Member.class, order.getMemberId());
					StringBuffer smsMsg = new StringBuffer();
					smsMsg.append("亲爱的耀点100用户，您所订购的商品已无货，为避免不必要的等待造成您额外的不便，我们必须很抱歉的通知您订单").append(orderId).append(
							"无法成立，相应的退款作业也会尽快进行，再次感谢您对耀点100的支持。【耀点100】");
					if (member.getMobile() != null && member.getMobile().length() > 0) {
						this.smsService.sendSms(member.getMobile(), smsMsg.toString(), orderId);
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
				// 发送购物金10元
				// Bonus bonus = new Bonus();
				// bonus.setMemberId(order.getMemberId());
				// bonus.setOrderId(orderId);
				// bonus.setStartDate(DateUtils.addDays(wo.getCreateDate(), 1));
				// bonus.setTrxDate(new Date());
				// bonus.setExpireDate(DateUtils.addDays(bonus.getStartDate(), 30));
				// bonus.setTrxAmount(new BigDecimal(10));
				// bonus.setDescription("断货补偿");
				// bonus.setTrxType("ORDER_FEEDBACK");
				// try {
				// memberService.saveOrUpdateBonus(bonus);
				// } catch (Exception e) {
				// e.printStackTrace();
				// }
			}
		}
	}

	/**
	 * 物流異常退款工單
	 * 
	 * @param woCreater
	 * @param orderId
	 * @param soId
	 * @param woContent
	 * @return
	 */
	@Override
	@Transactional(readOnly = false)
	public void createFailDeliverCancelOrder(String woCreater, String woContent, String orderId, String soId) {
		if (StringUtils.isBlank(orderId)) {
			return;
		}
		Orders order = (Orders) baseMgr.get(Orders.class, orderId);
		String questionTypeName = "FailDeliverCancelOrder";
		Map<String, String> values = new HashMap<String, String>();
		values.put("woCreater", woCreater);
		values.put("orderId", orderId);
		values.put("soId", soId);
		values.put("memberId", order.getMemberId());
		DetachedCriteria dc = DetachedCriteria.forClass(FromChannel.class);
		dc.add(Restrictions.eq("title", "WEB form"));
		Object[] channels = baseMgr.findByCriteria(dc);
		FromChannel channel = null;
		if (channels != null) {
			channel = ((FromChannel) channels[0]);
		}
		Question question = createQuestionBase(null, null, questionTypeName, values, woContent, woContent, channel, null);

		WorkOrder wo1 = workOrderService.createWorkOrder("SYSTEM", question.getId(), question.getShortDesc(), false, null);
		workOrderService.forwardOrder(wo1, woContent, "sms", "A-30-500-000", "8ae4838833c3bf2e0133c5529a84013a", 1);
	}

	public QuestionAttachService getQuestionAttachServiceRemote() {
		return questionAttachServiceRemote;
	}

	public void setQuestionAttachServiceRemote(QuestionAttachService questionAttachServiceRemote) {
		this.questionAttachServiceRemote = questionAttachServiceRemote;
	}

	public void createTmallWO(String orderId, String comment) {
		Map<String, String> values = new HashMap<String, String>();
		values.put("orderId", orderId);
		WorkOrder wo1 = createGeneralQuestionAndWo("tmallUpdateOrder", values, comment);
		workOrderService.forwardOrder(wo1, comment, "tmall", "T.tmall", "8ae4808d33f743370133f810f5770128",
				WorkOrder.PRIORITY.EMERGENCY.code());

	}

	public WorkOrder createGeneralQuestionAndWo(String questionTypeName, Map<String, String> props, String comment) {
		DetachedCriteria dc = DetachedCriteria.forClass(FromChannel.class);
		dc.add(Restrictions.eq("title", "内部人员"));
		Object[] channels = baseMgr.findByCriteria(dc);
		FromChannel channel = null;
		if (channels != null) {
			channel = ((FromChannel) channels[0]);
		}
		Question question = createQuestionBase(null, null, questionTypeName, props, comment, comment, channel, null);
		WorkOrder wo1 = workOrderService.createWorkOrder("SYSTEM", question.getId(), question.getShortDesc(), false, null);
		return wo1;
	}

	@Override
	@Transactional(readOnly = false)
	public void createCheckProductComment(String commentId, String memberId, String productName, String title,
			String content, String productId) {
		String woGroup = "C.01";
		String sql = "select ctgu.task_group_id from ec_category_main ecm, ec_product_main epm, crm_task_group_user ctgu "
				+ "where ecm.category_id = epm.main_category_id " + "and ctgu.task_group_id = ecm.orgnization_path "
				+ "and epm.product_id = '" + productId + "' ";
		List<Map<String, Object>> qList = jdbcTemplate.queryForList(sql);
		if (null != qList && !qList.isEmpty()) {
			woGroup = qList.get(0).get("task_group_id").toString();
		}
		String questionTypeName = "CheckProductComment";
		Map<String, String> values = new HashMap<String, String>();
		values.put("commentId", commentId);
		values.put("memberId", memberId);
		DetachedCriteria dc = DetachedCriteria.forClass(FromChannel.class);
		dc.add(Restrictions.eq("title", "WEB form"));
		Object[] channels = baseMgr.findByCriteria(dc);
		FromChannel channel = null;
		if (channels != null) {
			channel = ((FromChannel) channels[0]);
		}
		String comment = "商品名称：" + productName + "，主旨：" + title + "，内容：" + content;
		Question question = createQuestionBase(null, null, questionTypeName, values, "商品评价审核", comment, channel, memberId);
		WorkOrder wo = workOrderService.createWorkOrder("SYSTEM", question.getId(), question.getShortDesc(), false, null);
		workOrderService.forwardOrder(wo, comment, "sms", woGroup, "8ae48388342fec4701343b7fc59405e6", 1);
	}
}
